package com.svw.asmpcloud.conf;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.util.AntPathMatcher;

import com.svw.asmpcloud.handler.CustomHttpBasicServerAuthenticationEntryPoint;
import com.svw.asmpcloud.handler.CustomServerAccessDeniedHandler;
import com.svw.asmpcloud.handler.LoginFailureHandler;
import com.svw.asmpcloud.handler.LoginSuccessHandler;
import com.svw.asmpcloud.handler.SecurityContextRepository;
import com.svw.asmpcloud.handler.UriReactiveAuthorizationManager;

@EnableWebFluxSecurity
public class SecurityWebFluxConfig {
    // 自定义的鉴权服务，通过鉴权的才能继续访问某个请求
    @Autowired
    private UriReactiveAuthorizationManager uriReactiveAuthorizationManager;

    // 无权限访问被拒绝时的自定义处理器。如不自己处理，默认返回403错误
    @Autowired
    private CustomServerAccessDeniedHandler customServerAccessDeniedHandler;

    // 登录成功时调用的自定义处理类
    @Autowired
    private LoginSuccessHandler loginSuccessHandler;

    // 登录失败时调用的自定义处理类
    @Autowired
    private LoginFailureHandler loginFailureHandler;

    // 未登录访问资源时的处理类，若无此处理类，前端页面会弹出登录窗口
    @Autowired
    private CustomHttpBasicServerAuthenticationEntryPoint customHttpBasicServerAuthenticationEntryPoint;
    // 未登录访问资源时的处理类，若无此处理类，前端页面会弹出登录窗口
    @Autowired
    private SecurityContextRepository securityContextRepository;
    // security的鉴权排除列表
    private static final String[] excludedAuthPages = { "/auth/**", "/health", "/api/socket/**", "/base-core/product/try1", 
            "/swagger-ui/**", "/swagger-resources/**",
            "/v2/api-docs", "/webjars/**","/doc.html" };

    @Bean
    SecurityWebFilterChain webFluxSecurityFilterChain(ServerHttpSecurity http) throws Exception {
        http.authorizeExchange().pathMatchers(excludedAuthPages).permitAll() // 无需进行权限过滤的请求路径
                .pathMatchers(HttpMethod.OPTIONS).permitAll() // option 请求默认放行
                .and().authorizeExchange().pathMatchers("/**").access(uriReactiveAuthorizationManager)// 自定义的鉴权服务，通过鉴权的才能继续访问某个请求
                .anyExchange().authenticated().
                and().httpBasic().
                and().formLogin().loginPage("/auth/login").authenticationSuccessHandler(loginSuccessHandler) // 认证成功
                .authenticationFailureHandler(loginFailureHandler) // 登陆验证失败
                .and().securityContextRepository(securityContextRepository) // 为了支持jwt 自定义了这个类
                .exceptionHandling().authenticationEntryPoint(customHttpBasicServerAuthenticationEntryPoint) // 未登录访问资源时的处理类，若无此处理类，前端页面会弹出登录窗口
                .and().exceptionHandling().accessDeniedHandler(customServerAccessDeniedHandler)// 访问被拒绝时自定义处理器
                .and().csrf().disable()// 必须支持跨域
                .logout().logoutUrl("/auth/logout");
        return http.build();
    }

    // 密码加密
    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

    // 路径匹配器
    @Bean
    public AntPathMatcher antPathMatcher() {
        return new AntPathMatcher();
    }
}